package org.cb.core;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.imageio.ImageIO;

import org.cb.gui.MainGUI;
import org.cb.types.Font;
import org.cb.types.Letter;


public class FontLoader {
	ArrayList<Font> fonts = new ArrayList<Font>();

	public ArrayList<Font> getFonts() {
		return fonts;
	}
	
	public void loadFonts() {
		File mainFolder = new File("Fonts/");
		for( File f : mainFolder.listFiles()){
			//MainGUI.info("Loading Font: " + f.getName());
			Font Font = new Font();
			Font.name = f.getName();
			for(File f2 : f.listFiles()) {
				Letter l = new Letter();
				l.letter = (char) Integer.parseInt(f2.getName().replaceAll(".bmp", ""));
				l.image = trimImageFast(loadCharacter(f.getName(), l.letter));
				Font.letters.add(l);
			}
			fonts.add(Font);
        }
		MainGUI.info("Loaded Fonts");
	}
	
	private BufferedImage loadCharacter(String fontFolder, int decNumber) {
		try {
			return ImageIO.read(new File("Fonts/" + fontFolder + "/" + decNumber + ".bmp"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	private BufferedImage trimImageFast(BufferedImage img) {
		int i;
		Color col;
		if(imageHasShadow(img)) col = Color.red;
		else col = Color.white;
		if(col == Color.white) {
			if(!imageHasWhite(img)) return null;
		}
		Rectangle area = new Rectangle(img.getWidth() - 1, img.getHeight() - 1);
		for(i = 0; i < img.getWidth(); i++) {
			if(colorInLineVertical(img, col, area, i)) break;
		}
		area = new Rectangle(i, 0, area.width, area.height);
		for(i = (int)area.getWidth(); i > area.x + 1; i--) {
			if(colorInLineVertical(img, col, area, i)) break;	
		}
		if(i - area.x == 0) area = new Rectangle(area.x, area.y, 1, area.height);
		else area = new Rectangle(area.x, 0, i - area.x, area.height);
		for(i = 0; i < img.getHeight(); i++) {
			if(colorInLineHorizontal(img, col, area, i)) break;
		}
		area = new Rectangle(area.x, i, area.width, area.height);
		for(i = (int)area.getHeight(); i > area.y + 1; i--) {
			if(colorInLineHorizontal(img, col, area, i)) break;	
		}
		if(i - area.y == 0) area = new Rectangle(area.x, area.y, area.width, 1);
		else area = new Rectangle(area.x, area.y, area.width, (i - area.y) + 1);
		BufferedImage image = new BufferedImage(area.width, area.height, BufferedImage.TYPE_INT_RGB);
		image.getGraphics().drawImage(img, 0, 0, area.width, area.height, area.x, area.y, area.x + area.width, area.y + area.height, null);
		removeWhite(image);
		return image;
	}
	
	private boolean colorInLineVertical(BufferedImage img, Color col, Rectangle area, int line) {
		for (int y = area.y; y < area.y + area.getHeight(); y++) {
			if(SimilarColors(new Color(img.getRGB(line, y)), col, 0)) return true;
		}
		return false;
	}
	
	private boolean colorInLineHorizontal(BufferedImage img, Color col, Rectangle area, int line) {
		for (int x = area.x; x < area.x + area.getWidth(); x++) {
			if(SimilarColors(new Color(img.getRGB(x, line)), col, 0)) return true;
		}
		return false;
	}
	
	private boolean SimilarColors(Color a, Color b, int tolerance) {
		if (Math.abs(a.getRed() - b.getRed()) > tolerance) return false;
		if (Math.abs(a.getGreen() - b.getGreen()) > tolerance) return false;
		if (Math.abs(a.getBlue() - b.getBlue()) > tolerance) return false;
		return true;
	}
	
	private boolean imageHasShadow(BufferedImage img) {
		for(int x = 0; x < img.getWidth(); x++) {
			for(int y = 0; y < img.getHeight(); y++) {
				if(new Color(img.getRGB(x, y)).equals(Color.red)) return true;
			}
		}
		return false;
	}
	
	private boolean imageHasWhite(BufferedImage img) {
		for(int x = 0; x < img.getWidth(); x++) {
			for(int y = 0; y < img.getHeight(); y++) {
				if(new Color(img.getRGB(x, y)).equals(Color.white)) return true;
			}
		}
		return false;
	}
	
	private BufferedImage removeWhite(BufferedImage img) {
		for(int x = 0; x < img.getWidth(); x++) {
			for(int y = 0; y < img.getHeight(); y++) {
				if(new Color(img.getRGB(x, y)).equals(Color.white)) {
					setPixel(img, x, y, Color.black);
				}
			}
		}
		return img;
	}
	
	private void setPixel (BufferedImage image, int x, int y, Color color ) {
		  Graphics g = image.getGraphics();
		  g.setColor(color);
		  g.fillRect(x, y, 1, 1);
		  g.dispose();
	}
}
